package cn.demo.um.domain;

import java.util.*;
import java.time.LocalDateTime;
import java.util.function.Function;
import java.util.stream.Collectors;

import cn.demo.common.constant.CommonConstants;
import cn.demo.common.core.domain.entity.SysDept;
import cn.demo.common.utils.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.mybatisflex.annotation.Column;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import com.mybatisflex.annotation.Table;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.core.constant.SqlOperator;
import com.mybatisflex.core.query.SqlOperators;
import cn.demo.common.mybatisFlex.MyInsertListener;
import cn.demo.common.mybatisFlex.MyUpdateListener;
import cn.demo.common.annotation.Excel;
import io.swagger.v3.oas.annotations.media.Schema;
import com.fasterxml.jackson.annotation.JsonIgnore;
import cn.demo.common.core.domain.BaseEntity;
import com.mybatisflex.annotation.RelationOneToMany;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;

import static cn.demo.common.utils.DateUtils.YYYY_MM_DD;

/**
 * 客户端用户对象 um_client_user
 *
 * @author xtjun
 * @date 2024-06-03
 */
@EqualsAndHashCode(callSuper = true)
@Data
@Table(value = "um_client_user", onInsert = MyInsertListener.class, onUpdate = MyUpdateListener.class)
@Slf4j
public class UmClientUser extends BaseEntity {
    private static final long serialVersionUID = 1L;

    public static final String DELIMITER = "丨";


    @Id
    @Schema(description = "id")
    private String id;

    @Excel(name = "用户名")
    @Schema(description = "用户名")
    private String username;

    @Excel(name = "密码")
    @Schema(description = "密码")
    private String password;

    @Excel(name = "昵称")
    @Schema(description = "昵称")
    private String nickname;

    @Excel(name = "手机号码")
    @Schema(description = "手机号码")
    private String phone;

    @Excel(name = "邮箱")
    @Schema(description = "邮箱")
    private String eamil;

    @Excel(name = "用户头像")
    @Schema(description = "用户头像")
    private String avatar;

    @Excel(name = "真实姓名")
    @Schema(description = "真实姓名")
    private String realname;

    @Excel(name = "性别", dictType = "sys_user_sex")
    @Schema(description = "性别(字典:sys_user_sex)")
    private Integer sex;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Excel(name = "出生日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
    @Schema(description = "出生日期")
    private LocalDateTime birthday;

    @Excel(name = "微信公众号openid")
    @Schema(description = "微信公众号openid")
    private String wxmpOpenid;

    @Excel(name = "微信开放平台openid")
    @Schema(description = "微信开放平台openid")
    private String wxopenOpenid;

    @Excel(name = "微信小程序openid")
    @Schema(description = "微信小程序openid")
    private String wxmaOpenid;

    @Excel(name = "微信unionid")
    @Schema(description = "微信unionid")
    private String wxUnionid;

    @Excel(name = "积分")
    @Schema(description = "积分")
    private Long integral;

    @Excel(name = "总积分")
    @Schema(description = "总积分")
    private Long integralTotal;

    @Excel(name = "已使用积分")
    @Schema(description = "已使用积分")
    private Long integralUsed;

    @Excel(name = "认证状态", dictType = "auth_status")
    @Schema(description = "认证状态(字典:auth_status)")
    private Integer authStatus;

    @Excel(name = "状态", dictType = "sys_data_status")
    @Schema(description = "状态(字典:sys_data_status)")
    private Integer status;

    @Excel(name = "是否推荐", dictType = "sys_yes_no")
    @Schema(description = "是否推荐(字典:sys_yes_no)")
    private Integer isShow;

    @Excel(name = "部门id")
    @Schema(description = "部门id")
    private String deptId;

    @Column(ignore = true)
    @Schema(description = "部门信息")
    private SysDept deptInfo;

    @Schema(description = "用户属性值 列表")
    @RelationOneToMany(selfField = "id", targetField = "userId")
    @JsonIgnore
    private List<UmAttrData> attrDataList;

    @Schema(description = "用户属性值 map")
    private Map<String, Object> attrDataMap;

    @JsonIgnore
    @Schema(description = "属性值查询 map")
    private Map<String, String> attrQueryMap;

    @Column(ignore = true)
    @Schema(description = "是否关注")
    private Boolean isFocus;
    @Column(ignore = true)
    @Schema(description = "是否互关")
    private Boolean isFocusEachOther;
    @Column(ignore = true)
    @Schema(description = "匹配度分数")
    private Integer matchDegree;

    // 自定义字段的 SQL 操作符
    @JsonIgnore
    public static final SqlOperators operators = new SqlOperators() {{
        set(UmClientUser::getUsername, SqlOperator.LIKE);
        set(UmClientUser::getPassword, SqlOperator.EQUALS);
        set(UmClientUser::getNickname, SqlOperator.LIKE);
        set(UmClientUser::getPhone, SqlOperator.LIKE);
        set(UmClientUser::getEamil, SqlOperator.EQUALS);
        set(UmClientUser::getAvatar, SqlOperator.EQUALS);
        set(UmClientUser::getRealname, SqlOperator.LIKE);
        set(UmClientUser::getSex, SqlOperator.EQUALS);
        set(UmClientUser::getWxmpOpenid, SqlOperator.EQUALS);
        set(UmClientUser::getWxopenOpenid, SqlOperator.EQUALS);
        set(UmClientUser::getWxmaOpenid, SqlOperator.EQUALS);
        set(UmClientUser::getWxUnionid, SqlOperator.EQUALS);
        set(UmClientUser::getIntegral, SqlOperator.EQUALS);
        set(UmClientUser::getIntegralTotal, SqlOperator.EQUALS);
        set(UmClientUser::getIntegralUsed, SqlOperator.EQUALS);
        set(UmClientUser::getAuthStatus, SqlOperator.EQUALS);
        set(UmClientUser::getStatus, SqlOperator.EQUALS);
        set(UmClientUser::getIsShow, SqlOperator.EQUALS);
        set(UmClientUser::getDeptId, SqlOperator.EQUALS);
    }};

    public Map<String, Object> getAttrDataMap() {
        if (attrDataMap == null) {
            attrDataMap = new LinkedHashMap<>();
            if (!CollectionUtils.isEmpty(attrDataList)) {
                attrDataList.forEach(s->{
                    if (CommonConstants.YES.equals(s.getIsStandard())){
                        s.setAttrCode(UmAttrConf.CONDITION_PREFIX + s.getAttrCode());
                    }
                });
                Map<String, List<UmAttrData>> listMap = attrDataList.stream().collect(Collectors.groupingBy(UmAttrData::getAttrCode));
                listMap.forEach((k, v) -> {
                    List<String> vList = v.stream().map(UmAttrData::getAttrValue).toList();

                    attrDataMap.put(k, v.size() > 1 ? vList : vList.getFirst());
                });
            }
        }
        return attrDataMap;
    }

    public void setAttrDataMap(Map<String, Object> attrDataMap) {
        attrDataMap.entrySet().removeIf(entry -> entry.getKey().contains("_"));
        calcAge(attrDataMap);
        this.attrDataMap = attrDataMap;
        attrDataList = new ArrayList<>();
        attrDataMap.forEach((k, v) -> {
            if (v instanceof Collection<?>) {
                ((Collection<?>) v).forEach(s -> {
                    buildAttrData(k, s.toString());
                });
            } else {
                buildAttrData(k, v.toString());
            }
        });
    }

    private void buildAttrData(String k, String s) {
        UmAttrData attrData = new UmAttrData();
        if (k.startsWith(UmAttrConf.CONDITION_PREFIX)){
            attrData.setIsStandard(1);
            attrData.setAttrCode(k.replace(UmAttrConf.CONDITION_PREFIX,""));
        }else {
            attrData.setIsStandard(0);
            attrData.setAttrCode(k);
        }
        attrData.setAttrValue(s);
        attrDataList.add(attrData);
    }

    private void calcAge(Map<String, Object> attrDataMap) {
        if (null != attrDataMap.get("SR") && null == attrDataMap.get("NL") && StringUtils.isNotEmpty(attrDataMap.get("SR").toString())) {
            Date date = DateUtils.parseDate(attrDataMap.get("SR").toString());
            Date nowDate = DateUtils.getNowDate(YYYY_MM_DD);
            attrDataMap.put("NL", (nowDate.getTime() - date.getTime()) / 31556927799L);
        }
    }
}
